import fs from "node:fs";
import path from "node:path";
import { defineConfig } from "vite";
import VuePlugin from "@vitejs/plugin-vue";
import VueJsxPlugin from "@vitejs/plugin-vue-jsx";

import Markdown from "vite-plugin-md";
import MarkdownItContainer from "markdown-it-container";
import { SyncMarkdown, BeautifulCode } from "@design/plugins";

import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import { VantResolver, VantImports } from "@vant/auto-import-resolver";

export default async function () {
    const exampleDir = path.resolve(__dirname, "../docs");
    const packageJSON = path.resolve(__dirname, "../package.json");
    let additionalData = `@import "@/style/variable.less"; `;

    if (process.env.NODE_ENV === "development") {
        additionalData += `@import "design/dev/variable";`;
    }
    const packageJson = JSON.parse(
        fs.readFileSync(packageJSON, { encoding: "utf-8" }) || "{}",
    );

    return defineConfig({
        define: {
            __PACKAGE_VERSION__: JSON.stringify(packageJson.version),
            __PROJECT_INFO__: JSON.stringify(packageJson.repository),
        },
        build: {
            outDir: "bundle",
            assetsDir: "asset",
            rollupOptions: {
                output: {
                    chunkFileNames: "asset/js/[name].[hash].js",
                    assetFileNames: (assetInfo) => {
                        let dirname = "asset/";
                        const filename = assetInfo.name;

                        if (filename?.endsWith("css")) dirname += "css/";
                        else if (
                            /\.(png|jpg|jpeg|ico|gif)$/.test(filename as string)
                        )
                            dirname += "img/";
                        else dirname += "other";

                        return dirname + "[name].[hash][extname]";
                    },
                },
            },
        },
        resolve: {
            alias: {
                "@": path.resolve(__dirname, "./"),
                "@docs": exampleDir,
            },
        },
        css: {
            preprocessorOptions: {
                less: {
                    additionalData,
                },
            },
        },
        server: {
            host: "0.0.0.0",
        },
        plugins: [
            {
                ...BeautifulCode.default(),
            },
            AutoImport({
                imports: [VantImports()],
                resolvers: [VantResolver(), ElementPlusResolver()],
            }),
            Components({
                resolvers: [VantResolver(), ElementPlusResolver()],
            }),
            VuePlugin({ include: [/\.vue$/, /\.md$/] }),
            VueJsxPlugin(),
            SyncMarkdown.default({
                demoDirPath: path.resolve(exampleDir, "example"),
            }),
            Markdown({
                markdownItSetup(md) {
                    md.use(MarkdownItContainer, "demo", {
                        validate: (params: string) =>
                            params.trim().match(/^demo\s*(.*)$/),
                        render(tokens: Array<any>, idx: number) {
                            if (tokens[idx].nesting === 1) {
                                let content = "";
                                let i = idx + 1;
                                while (
                                    i < tokens.length &&
                                    tokens[i].type !== "container_demo_close"
                                ) {
                                    content += tokens[i].content;
                                    i++;
                                }
                                const source = content.trim();
                                let code = "";
                                const filePath = path.resolve(
                                    exampleDir,
                                    `example/${source}.vue`,
                                );
                                if (fs.existsSync(filePath))
                                    code = fs.readFileSync(filePath, {
                                        encoding: "utf-8",
                                    });
                                return `<DemoBlock code="${encodeURIComponent(code)}" source="${source + ".vue"}">\n`;
                            }
                            return "</DemoBlock>\n";
                        },
                    });
                },
            }),
        ],
    });
}
